package org.one.stone.soup.grfxML;

import java.lang.reflect.Constructor;

import org.one.stone.soup.mjdb.data.field.ArrayField;
import org.one.stone.soup.mjdb.data.field.CompareException;
import org.one.stone.soup.mjdb.data.field.DataLinker;
import org.one.stone.soup.mjdb.data.field.Field;
import org.one.stone.soup.mjdb.data.field.LockException;
import org.one.stone.soup.mjdb.data.field.LockOwner;
import org.one.stone.soup.mjdb.data.field.Lockable;
import org.one.stone.soup.xml.XmlElement;
  /*
 * Copyright 2000-2001 Wet-Wired.com Ltd.,
 * Portsmouth England
 * All rights reserved.
 */

/**
	*
	* @author Nik Cross
*/
public  class DataStore extends ArrayField implements IArray,DataLinker,LockOwner{
	public static String DEFAULT_ID="_Store";

	private String buildData = null;
	private GrfxMLEngine engine;

public DataStore(GrfxMLEngine engine) {

	this.engine = engine;

	try{
		setId(DEFAULT_ID,this);
	}
	catch(LockException le){} //Dummy catch
}
public void add(Field data,Object source) throws LockException
{
	add(data,source,false);
}
public void add(Field data, Object source, boolean allowUnnamedData) throws LockException {

	if (!allowUnnamedData && NameHelper.isSystemName(data.getId()))
		return;

	_add(data, source);
}
public void buildFromgrfxML(String path,XmlElement xml)
{
	buildFromgrfxML(path,xml,false);
}
public void buildFromgrfxML(String path,XmlElement xml,boolean allowUnnamedData)
{

	String name = xml.getAttributeValueByName(Token.ID);
	if(name!=null)
	{
		try{
			setId(name,this);
		}
		catch(LockException le){} //Dummy catch
	}

	XmlElement element;

	for(int loop=0;loop<xml.getElementCount();loop++)
	{
	  element = xml.getElementByIndex(loop);

	 if(element!=null)
	 {
	  try{
		Class clazz  = Class.forName( NameHelper.toClassName(element.getName()) );

		Constructor constructor = null;
		try{
			constructor = clazz.getConstructor( new Class[]{Class.forName("org.one.stone.soup.grfxML.GrfxMLEngine")} );
		}
		catch(NoSuchMethodException nme){}

		Field newItem = null;

		if(constructor!=null)
		{
			newItem = (Field)constructor.newInstance(new Object[]{engine} );
		}
		else
		{
			newItem = (Field)clazz.newInstance();
		}

		clazz.
			getMethod(NameHelper.BUILD_METHOD,NameHelper.BUILD_SIG).
				invoke(newItem,new Object[]{element});

		add(newItem,this,allowUnnamedData);
	  }
	  catch(ClassNotFoundException cnf)
	  {		//Error message wrong ?
			GrfxMLException.warning( GrfxMLException.WARNING_UNRECOGNISED_TAG_CODE ,new Object[]{element.getName(),"store",""+element.getStartLineNo()} );
	  }
	  catch(Exception e)
	  {
		e.printStackTrace();
	  }// Major exception handleing needed here (and in this function)
	 }

	}
	storeBuildData(true);
	
	for(int loop=0;loop<size();loop++)
	{
		Field newItem = get(loop);
		
		if(path!=null && !(NameHelper.isReferenceName(newItem.getId()) || newItem.isReference ))
		{
			try{
				newItem.setId( path+"."+newItem.getId(),this );
			}
			catch(Exception e){}
		}
	}
}
public void buildFromgrfxML(XmlElement xml)
{

	String name = xml.getAttributeValueByName(Token.ID);
	if(name!=null)
	{
		try{
			setId(name,this);
		}
		catch(LockException le){} //Dummy catch
	}

	XmlElement element;

	for(int loop=0;loop<xml.getElementCount();loop++)
	{
	  element = xml.getElementByIndex(loop);

	 if(element!=null)
	 {
	  try{
		Class clazz  = Class.forName( NameHelper.toClassName(element.getName()) );

		//Field newItem = (Field)clazz.newInstance();
		Constructor constructor = null;
		try{
			constructor = clazz.getConstructor( new Class[]{Class.forName("org.one.stone.soup.grfxML.GrfxMLEngine")} );
		}
		catch(NoSuchMethodException nme){}

		Field newItem = null;

		if(constructor!=null)
		{
			newItem = (Field)constructor.newInstance(new Object[]{engine} );
		}
		else
		{
			newItem = (Field)clazz.newInstance();
		}

		clazz.
			getMethod(NameHelper.BUILD_METHOD,NameHelper.BUILD_SIG).
				invoke(newItem,new Object[]{element});
		add(newItem,this);
	  }
	  catch(ClassNotFoundException cnf)
	  {		//Error message wrong ?
			GrfxMLException.warning( GrfxMLException.WARNING_UNRECOGNISED_TAG_CODE ,new Object[]{element.getName(),"store",""+element.getStartLineNo()} );
	  }
	  catch(Exception e)
	  {
		e.printStackTrace();
	  }// Major exception handleing needed here (and in this function)
	 }

	}
	
	storeBuildData(true);
}

public void storeBuildData(boolean state)
{
	if(state=false)
	{
		buildData=null;
	}
	else
	{
		StringBuffer buffer = new StringBuffer();
		dataTogrfxML(buffer);
		buildData = buffer.toString();
	}
}

public boolean canForceUnlock(Lockable data, LockOwner requester) {
	return true;
}
/**
 * compare method comment.
 */
public int compare(Field target) throws CompareException {
	return 0;
}
public void copyFromgrfxML(String path,XmlElement xml)
{
	copyFromgrfxML(path,xml,false);
}
public void copyFromgrfxML(String path,XmlElement xml,boolean allowUnnamedData)
{
	XmlElement element;

	int loop;
	for(loop=0;loop<xml.getElementCount();loop++)
	{
	  element = xml.getElementByIndex(loop);

	 if(element!=null)
	 {
	  if(loop<size())
	  {
		  ((ITag)get(loop)).copyFromgrfxML( element );
	  }
	  else
	  {
		  try{
			Class clazz  = Class.forName( NameHelper.toClassName(element.getName()) );
			Field newItem = (Field)clazz.newInstance();

			clazz.
				getMethod(NameHelper.BUILD_METHOD,NameHelper.BUILD_SIG).
					invoke(newItem,new Object[]{element});

			if(path!=null && !(NameHelper.isReferenceName(newItem.getId()) || newItem.isReference ))
			{
				newItem.setId( path+"."+newItem.getId(),this );
			}

			add(newItem,this,allowUnnamedData);
		  }
		  catch(ClassNotFoundException cnf)
		  {
				GrfxMLException.warning( GrfxMLException.WARNING_UNRECOGNISED_TAG_CODE ,new Object[]{element.getName(),"store",""+element.getStartLineNo()} );
		  }
		  catch(Exception e)
		  {
			e.printStackTrace();
		  }// Major exception handleing needed here (and in this function)
	  }
	 }
	}

	while(loop<size())
	{
		try{
			remove( size()-1,this );
		}catch(LockException le){}
	}
}
public void copyFromgrfxML(XmlElement xml)
{
	XmlElement element;

	int loop;
	for(loop=0;loop<xml.getElementCount();loop++)
	{
	  element = xml.getElementByIndex(loop);

	 if(element!=null)
	 {
	  if(loop<size())
	  {
		  ((ITag)get(loop)).copyFromgrfxML( element );
	  }
	  else
	  {
		  try{
			Class clazz  = Class.forName( NameHelper.toClassName(element.getName()) );
			Field newItem = (Field)clazz.newInstance();
			clazz.
				getMethod(NameHelper.BUILD_METHOD,NameHelper.BUILD_SIG).
					invoke(newItem,new Object[]{element});
			add(newItem,this);
		  }
		  catch(ClassNotFoundException cnf)
		  {
				GrfxMLException.warning( GrfxMLException.WARNING_UNRECOGNISED_TAG_CODE ,new Object[]{element.getName(),"store",""+element.getStartLineNo()} );
		  }
		  catch(Exception e)
		  {
			e.printStackTrace();
		  }// Major exception handleing needed here (and in this function)
	  }
	 }
	}

	while(loop<size())
	{
		try{
			remove( size()-1,this );
		}catch(LockException le){}
	}
}
public Field get(int index)
{
	return (Field)_get(index);
}
public DataStore getClone() {

	DataStore newStore = new DataStore(engine);

	for(int loop=0;loop<size();loop++)
	{
		try{
		 newStore.add( (Field)
			get(loop)
				.getClass()
					.getMethod( "getClone",new Class[]{})
						.invoke( (Object)get(loop),new Object[]{}),
			this
		 );
		}
		catch(Exception e){}// need exception handling
	}

	return newStore;
}
public DataStore getClone(String path) {

	DataStore newStore = new DataStore(engine);

	GrfxMLStoreProcessor.setCloneName( path,this,newStore );

	for(int loop=0;loop<size();loop++)
	{
		try{
		 newStore.add( (Field)
			get(loop)
				.getClass()
					.getMethod( "getClone",new Class[]{Class.forName("java.lang.String")} )
						.invoke( (Object)get(loop),new Object[]{path} ),
			this
		 );
		}
		catch(Exception e){
			e.printStackTrace();
		}// need exception handling
	}

	return newStore;
}
public String getMemberName() {
	return Token.ANY;
}
/**
 * getValue method comment.
 */
public String getValue(String name) {
	return null;
}
public void insert(Field data,int index,Object source) throws LockException
{
	_insert(data,index,source);
}
public void notifyForcedUnlock() {}
public void register(DataLinker store) {
	super.register(store);
}
public void remove(int index,Object source) throws LockException
{
	_remove(index,source);
}
public void remove(Field data,Object source) throws LockException
{
	_remove(data,source);
}
public void replace(Field oldObj, Field newObj) {
	replace(oldObj,newObj,false);
}
public void replace(Field oldObj, Field newObj,boolean recursive) {
	for(int loop=0;loop<size();loop++)
	{
		if(get(loop)==oldObj)
		{
			try{
				set((Field)newObj,loop,this);
			}
			catch(LockException le){}//dummy catch
		}
		((ITag)get(loop)).replace(oldObj,newObj,recursive);
	}
}
public GrfxMLEngine getEngine()
{
	return engine;
}

public void resetChanged() {
	super.resetChanged();
}
public void set(Field data,int index,Object source) throws LockException
{
	_set(data,index,source);
}
private void dataTogrfxML(StringBuffer xml) {

	for (int loop = 0; loop < size(); loop++) {
		try {
			xml.append( ((ITag) get(loop)).togrfxML(NameHelper.systemToTagName((String) get(loop).getClass().getField("DEFAULT_ID").get(get(loop)))) );
		} catch (Exception e) {} //dummy catch
	}
}

public String togrfxML(String name) {

	StringBuffer xml = new StringBuffer("<");

	xml.append( name );
	if(!NameHelper.isSystemName(getId()))
	{
		xml .append(" id=\""+getId()+"\"");
	}
	xml.append(">");
	
	if(buildData==null)
	{
		dataTogrfxML(xml);
	}
	else
	{
		xml.append(buildData);
	}
	xml.append( "</" + name + ">\n" );

	return xml.toString();
}
public String togrfxML(String name,TagModifier modifier) {
	return togrfxML(name);
}
public String toString() {

	String xml = "<" + DEFAULT_ID.substring(1);
	xml += "/>";
	xml += "\n<!-- ";
	for (int loop = 0; loop < size(); loop++) {
		try {
			xml += "\nDATA[" + loop + "] isR="+get(loop).isReference+": " + NameHelper.systemToTagName((String) get(loop).getClass().getField("DEFAULT_ID").get(get(loop))) + ":\tID=" + ((ITag) get(loop)).getId() + " \tREF=" + ((Field) get(loop)).getRef() + " \t= " + ((ITag) get(loop)).toString();
		} catch (Exception e) {
		} //dummy catch

	}
	xml += "\n -->";

	return xml;
}
}
